/* **********************************************************************************
 *
 * Copyright (c) TMF.AscendedThemeKit.Unthemed.NET Project. All rights reserved.
 *
 * This source code is subject to terms and conditions of the Shared Source License
 * for TMF.AscendedThemeKit.Unthemed. A copy of the license can be found in the License.html file
 * at the root of this distribution. If you can not locate the Shared Source License
 * for TMF.AscendedThemeKit.Unthemed, please send an email to ascend_adm@hotmail.com.
 * By using this source code in any fashion, you are agreeing to be bound by
 * the terms of the Shared Source License for TMF.AscendedThemeKit.Unthemed.NET.
 *
 * You must not remove this notice, or any other, from this software.
 *
 * **********************************************************************************/

using TMF.AscendedThemeKit.Unthemed.Resources;
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.Collections;

namespace TMF.AscendedThemeKit.Unthemed.Windows.Forms
{
    /// <summary>
    ///  Renders a gradient tab based on properties.
    /// </summary>
    public class GradientTabRender : IDisposable
    {
        private Color _adjustedBorderColorAll;
        private Color _adjustedBorderColorBottom;
        private Color _adjustedBorderColorLeft;
        private Color _adjustedBorderColorRight;
        private Color _adjustedBorderColorTop;
        private Border _border = new Border(1);
        private BorderColor _borderColor = new BorderColor(SystemColors.ControlDarkDark);
        private Rectangle _displayRectangle;
        private Rectangle _leftArrowButtonRectangle;
        private Rectangle _rightArrowButtonRectangle;
        private bool _enabled = true;
        private bool _antiAlias;
        private Color _backColor;
        private int _tabHeight;
        private GradientTab _parentGradientTab;
        private GradientNavigationButtonRender _gradientNavigationButtonRender;
        private GradientNavigationButtonRender _gradientNavigationButtonRenderArrow;
        private int _highlightIndex;
        private int _activeIndex;
        private int _displayButtonCount;
        private bool _disposed;
        private bool _useCompatibleTextRendering;
        private ArrayList _displayOrder = new ArrayList();
        private Color _defaultTabGradientHighColor;
        private Color _defaultTabGradientLowColor;
        private Color _tabBorderColor;
        private RenderMode _renderMode;
        private bool _rightToLeft;
        private ContentAlignment _defaultTabTextAlign;
        private ContentAlignment _defaultTabImageAlign;
        private Color _defaultTabForeColor;
        private Color _defaultTabActiveGradientHighColor;
        private Color _defaultTabActiveGradientLowColor;
        private Color _defaultTabHighlightGradientHighColor;
        private Color _defaultTabHighlightGradientLowColor;
        private GradientTabAlignment _alignment;
        private bool _multiline;
        private GradientTabSizeMode _gradientTabSizeMode;
        private int _tabWidth;
        private Color _controlColor;
        private int _tabTop = 0;
        private int _tabTopActiveOffset = 1;
        private int _tabTopOffset = 3;
        private bool _hasTabOverflow;
        private bool _isLeftArrowButtonHighlighted;
        private bool _isRightArrowButtonHighlighted;
        private bool _isRightArrowButtonActive;
        private bool _isLeftArrowButtonActive;
        private int _startingTabIndexOffset = 0;
        private bool _isLeftArrowButtonEnabled;
        private bool _isRightArrowButtonEnabled = true;
        private int _canShowTabIndex = 0;

        /// <summary>
        /// Occurs when the AntiAlias property changes.
        /// </summary>
        [ResourceDescriptionAttribute("AntiAliasChangedDescription"), ResourceCategoryAttribute("PropertyChangedCategory")]
        public event EventHandler AntiAliasChanged;

        /// <summary>
        /// Occurs when the Border property changes.
        /// </summary>
        [ResourceDescriptionAttribute("BorderChangedDescription"), ResourceCategoryAttribute("PropertyChangedCategory")]
        public event EventHandler BorderChanged;

        /// <summary>
        /// Occurs when the BorderColor property changes.
        /// </summary>
        [ResourceDescriptionAttribute("BorderColorChangedDescription"), ResourceCategoryAttribute("PropertyChangedCategory")]
        public event EventHandler BorderColorChanged;

        /// <summary>
        /// Occurs when the BackColor property changes. 
        /// </summary>
        public event EventHandler BackColorChanged;

        /// <summary>
        /// Occurs when the Enabled property changes.
        /// </summary>
        internal event EventHandler EnabledChanged;

        /// <summary>
        /// Initializes a new instance of the GradientTabRender class.
        /// </summary>
        /// <param name="parentControl">The parent gradient tab control.</param>
        public GradientTabRender(GradientTab parentControl)
        {
            if (parentControl == null)
            {
                throw new ArgumentNullException("parentControl");

            }
            
            this._parentGradientTab = parentControl;

            this._renderMode = RenderMode.Gradient;
            this._defaultTabTextAlign = ContentAlignment.MiddleLeft;
            this._defaultTabImageAlign = ContentAlignment.MiddleLeft;
            this._defaultTabForeColor = SystemColors.ControlText;
            this._defaultTabGradientHighColor = SystemColors.ButtonHighlight;
            this._defaultTabGradientLowColor = SystemColors.GradientActiveCaption;
            this._defaultTabActiveGradientHighColor = Color.FromArgb(255, 225, 155);
            this._defaultTabActiveGradientLowColor = Color.FromArgb(255, 165, 78);
            this._defaultTabHighlightGradientHighColor = Color.White;
            this._defaultTabHighlightGradientLowColor = Color.FromArgb(255, 165, 78);

            this._gradientNavigationButtonRender = new GradientNavigationButtonRender();
            this._gradientNavigationButtonRender.GradientHighColor = SystemColors.ButtonHighlight;
            this._gradientNavigationButtonRender.GradientLowColor = SystemColors.GradientActiveCaption;
            this._gradientNavigationButtonRender.ForeColor = SystemColors.ControlText;
            this._gradientNavigationButtonRender.TextAlign = ContentAlignment.MiddleLeft;
            this._gradientNavigationButtonRender.RenderMode = this._renderMode;
            this._gradientNavigationButtonRender.Border = new Border(0, 1, 1, 0);
            this._gradientNavigationButtonRender.BorderColor = new BorderColor(this._tabBorderColor);
            this._gradientNavigationButtonRender.Padding = new Padding(4, 0, 4, 0);

            this._gradientNavigationButtonRenderArrow = new GradientNavigationButtonRender();
            this._gradientNavigationButtonRenderArrow.GradientHighColor = SystemColors.ButtonHighlight;
            this._gradientNavigationButtonRenderArrow.GradientLowColor = SystemColors.GradientActiveCaption;
            this._gradientNavigationButtonRenderArrow.ForeColor = SystemColors.ControlText;
            this._gradientNavigationButtonRenderArrow.TextAlign = ContentAlignment.MiddleCenter;
            this._gradientNavigationButtonRenderArrow.ImageAlign = ContentAlignment.MiddleCenter;
            this._gradientNavigationButtonRenderArrow.RenderMode = this._renderMode;
            this._gradientNavigationButtonRenderArrow.Border = new Border(1);
            this._gradientNavigationButtonRenderArrow.BorderColor = new BorderColor(this._tabBorderColor);

            this._tabBorderColor = SystemColors.ControlDarkDark;
            this._controlColor = SystemColors.ControlLightLight;


            this._tabHeight = 18;
            this._tabWidth = 58;
            this._highlightIndex = -1;

            this._alignment = GradientTabAlignment.Top;
            this._gradientTabSizeMode = GradientTabSizeMode.Normal;

        }

        /// <summary>
        /// Gets or sets the border for the control.
        /// </summary>
        /// <value>
        /// 	<para>
        /// Border. An object of type Border representing the control's border width characteristics.
        /// </para>
        /// 	<para>
        /// This property is read/write.
        /// </para>
        /// </value>
        /// <remarks>
        /// For containers such as GradientPanel and GradientCaption, the Border property gets or sets their respective border widths inside the DisplayRectangle.
        /// </remarks>
        public Border Border
        {
            get
            {
                return this._border;

            }

            set
            {
                if (value == this.Border)
                {
                    return;

                }

                this._border = value;

                this.OnBorderChanged(new EventArgs());

            }

        }

        /// <summary>
        /// Gets or sets the border color(s) for the control.
        /// </summary>
        /// <value>
        /// <para>
        /// BorderColor. An object of type Border representing the control's border color characteristics.
        /// </para>
        /// <para>
        /// This property is read/write.
        /// </para>
        /// </value>
        /// <remarks>
        /// For containers such as GradientPanel and GradientCaption, the BorderColor property gets or sets their respective border colors inside the DisplayRectangle.
        /// </remarks>
        public BorderColor BorderColor
        {
            get
            {
                return this._borderColor;

            }

            set
            {
                if (value == this._borderColor)
                {
                    return;

                }

                this._borderColor = value;

                this.CreateColors();

                this.OnBorderColorChanged(new EventArgs());

            }

        }

        /// <summary>
        /// Gets or sets the control color
        /// </summary>
        public Color ControlColor
        {
            get 
            { 
                return this._controlColor;
            
            }

            set 
            { 
                this._controlColor = value;
            
            }

        }

        /// <summary>
        /// Gets or sets a value indicating whether the control can respond to user interaction.
        /// </summary>
        /// <value>
        /// 	<para>
        /// System.Boolean . true if the control can respond to user interaction; otherwise, false. The default is true. 
        /// </para>
        /// 	<para>
        /// This property is read/write. 
        /// </para>
        /// </value>
        public bool Enabled
        {
            get
            {
                return this._enabled;

            }

            set
            {
                if (value == this._enabled)
                {
                    return;

                }

                this._enabled = value;

                this.CreateColors();

            }

        }

        /// <summary>
        /// The display rectangle to render to.
        /// </summary>
        public Rectangle DisplayRectangle
        {
            get
            {
                return this._displayRectangle;

            }

            set
            {
                this._displayRectangle = value;

            }

        }

        /// <summary>
        /// Gets or sets the area of the control (for example, along the top) where the tabs are aligned.
        /// </summary>
        public GradientTabAlignment Alignment
        {
            get
            {
                return this._alignment;

            }

            set
            {
                if(this._alignment == value)
                {
                    return;

                }

                this._alignment = value;

                this.SetTabLocationValues();

            }

        }

        /// <summary>
        /// Specifies the rendering hint for the control.
        /// </summary>
        /// <value>
        /// 	<para>
        /// System.Boolean . Specifies if the rendering should use antialiasing.
        /// </para>
        /// 	<para>
        /// This property is read/write. 
        /// </para>
        /// </value>
        public bool AntiAlias
        {
            get
            {
                return this._antiAlias;

            }

            set
            {
                if (value == this._antiAlias)
                {
                    return;

                }

                this._antiAlias = value;

                this.CreateColors();

                this.OnAntiAliasChanged(new EventArgs());

            }

        }

        /// <summary>
        /// Specifies the back color for the control.
        /// </summary>
        /// <value>
        /// 	<para>
        /// System.Drawing.Color . Specifies the color to use on the background.
        /// </para>
        /// 	<para>
        /// This property is read/write. 
        /// </para>
        /// </value>
        public Color BackColor
        {
            get
            {
                return this._backColor;

            }

            set
            {
                if (value == this._backColor)
                {
                    return;

                }

                this._backColor = value;

                this.OnBackColorChanged(new EventArgs());

            }

        }

        internal Rectangle PanelRectangle
        {
            get
            {
                int left = 0;
                int right = 0;
                int top = 0;
                int bottom = 0;

                switch (this.Alignment)
                {
                    case GradientTabAlignment.Bottom:
                        bottom = this.TabHeight;
                        break;

                    case GradientTabAlignment.Left:
                        left = this.TabHeight;
                        break;

                    case GradientTabAlignment.Right:
                        right = this.TabHeight;
                        break;

                    default:
                        top = this.TabHeight;
                        break;

                }

                return new Rectangle(left, top, (this.DisplayRectangle.Width - (left + right)), (this.DisplayRectangle.Height - (top + bottom)));

            }

        }

        /// <summary>
        /// Gets or sets the way that the control's tabs are sized. 
        /// </summary>
        public GradientTabSizeMode SizeMode
        {
            get
            {
                return this._gradientTabSizeMode;

            }

            set
            {
                this._gradientTabSizeMode = value;

            }

        }

        /// <summary>
        /// Gets or sets the index offset to start the tab rendering at.
        /// </summary>
        public int StartingTabIndexOffset
        {
            get
            {
                return this._startingTabIndexOffset;

            }

            set
            {
                this._startingTabIndexOffset = value;

                if (this._startingTabIndexOffset > 0)
                {
                    this._isLeftArrowButtonEnabled = true;

                }
                else
                {
                    this._isLeftArrowButtonEnabled = false;

                }

                if (this._startingTabIndexOffset < (this._parentGradientTab.GradientTabPages.DisplayCount - 1))
                {
                    this._isRightArrowButtonEnabled = true;

                }
                else
                {
                    this._isRightArrowButtonEnabled = false;

                }

            }

        }

        /// <summary>
        /// Gets if the tabs are larger than the available display area.
        /// </summary>
        public bool HasTabOverflow
        {
            get
            {
                return this._hasTabOverflow;

            }

        }

        /// <summary>
        /// Gets or sets the current highlighted button index.
        /// </summary>
        public int HighlightIndex
        {
            get
            {
                return this._highlightIndex;

            }

            set
            {
                this._highlightIndex = value;

            }

        }

        /// <summary>
        /// Gets or sets if the left arrow button is active.
        /// </summary>
        public bool IsLeftArrowButtonActive
        {
            get
            {
                return this._isLeftArrowButtonActive;

            }

            set
            {
                this._isLeftArrowButtonActive = value;
                this._isRightArrowButtonActive = false;

            }

        }

        /// <summary>
        /// Gets or sets if the left arrow button is enabled.
        /// </summary>
        public bool IsLeftArrowButtonEnabled
        {
            get
            {
                return this._isLeftArrowButtonEnabled;

            }

            set
            {
                this._isLeftArrowButtonEnabled = value;

            }

        }

        /// <summary>
        /// Gets or sets if the left arrow button is highlighted.
        /// </summary>
        public bool IsLeftArrowButtonHighlighted
        {
            get
            {
                return this._isLeftArrowButtonHighlighted;

            }

            set
            {
                this._isLeftArrowButtonHighlighted = value;
                this._isRightArrowButtonHighlighted = false;

            }

        }

        /// <summary>
        /// Gets or sets if the right arrow button is active.
        /// </summary>
        public bool IsRightArrowButtonActive
        {
            get
            {
                return this._isRightArrowButtonActive;

            }

            set
            {
                this._isRightArrowButtonActive = value;
                this._isLeftArrowButtonActive = false;

            }

        }

        /// <summary>
        /// Gets or sets if the right arrow button is enabled.
        /// </summary>
        public bool IsRightArrowButtonEnabled
        {
            get
            {
                return this._isRightArrowButtonEnabled;

            }

            set
            {
                this._isRightArrowButtonEnabled = value;

            }

        }

        /// <summary>
        /// Gets or sets if the right arrow button is highlighted.
        /// </summary>
        public bool IsRightArrowButtonHighlighted
        {
            get
            {
                return this._isRightArrowButtonHighlighted;

            }

            set
            {
                this._isRightArrowButtonHighlighted = value;
                this._isLeftArrowButtonHighlighted = false;

            }

        }

        /// <summary>
        /// Gets the rectangle for the left arrow button.
        /// </summary>
        public Rectangle LeftArrowButtonRectangle
        {
            get
            {
                return this._leftArrowButtonRectangle;

            }

        }

        /// <summary>
        /// Gets or sets a value indicating whether more than one row of tabs can be displayed. 
        /// </summary>
        public bool Multiline
        {
            get
            {
                return this._multiline;

            }

            set
            {
                this._multiline = value;

            }

        }

        /// <summary>
        /// Specifies the painting style applied to the background in a control.
        /// </summary>
        public RenderMode RenderMode
        {
            get
            {
                return this._renderMode;

            }

            set
            {
                if (value == this._renderMode)
                {
                    return;

                }

                this._renderMode = value;

                this.ResetRenderMode();

            }

        }

        /// <summary>
        /// Gets the rectangle for the right arrow button.
        /// </summary>
        public Rectangle RightArrowButtonRectangle
        {
            get
            {
                return this._rightArrowButtonRectangle;

            }

        }

        /// <summary>
        /// Gets or sets the current active buton index.
        /// </summary>
        public int ActiveIndex
        {
            get
            {
                return this._activeIndex;

            }

            set
            {
                if (this._activeIndex == value)
                {
                    return;

                }

                this._activeIndex = value;

                this.MoveActiveTabIntoView();

            }

        }

        /// <summary>
        /// Gets or sets the tab active gradient high color.
        /// </summary>
        public Color TabActiveGradientHighColor
        {
            get
            {
                return this._defaultTabActiveGradientHighColor;

            }

            set
            {
                if (value == this._defaultTabActiveGradientHighColor)
                {
                    return;

                }

                this._defaultTabActiveGradientHighColor = value;
                this._gradientNavigationButtonRender.ActiveGradientHighColor = value;

            }

        }

        /// <summary>
        /// Gets or sets the tab active gradient low color.
        /// </summary>
        public Color TabActiveGradientLowColor
        {
            get
            {
                return this._defaultTabActiveGradientLowColor;

            }

            set
            {
                if (value == this._defaultTabActiveGradientLowColor)
                {
                    return;

                }

                this._defaultTabActiveGradientLowColor = value;
                this._gradientNavigationButtonRender.ActiveGradientLowColor = value;

            }

        }

        /// <summary>
        /// Gets or sets the tab border color.
        /// </summary>
        public Color TabBorderColor
        {
            get
            {
                return this._tabBorderColor;

            }

            set
            {
                if (value == this._tabBorderColor)
                {
                    return;

                }

                this._tabBorderColor = value;

            }

        }

        /// <summary>
        /// Gets or sets the tab forecolor.
        /// </summary>
        public Color TabForeColor
        {
            get
            {
                return this._defaultTabForeColor;

            }

            set
            {
                this._defaultTabForeColor = value;
                this._gradientNavigationButtonRender.ForeColor = value;

            }

        }

        /// <summary>
        /// Gets or sets the tab font.
        /// </summary>
        public Font TabFont
        {
            get
            {
                return this._gradientNavigationButtonRender.Font;

            }

            set
            {
                this._gradientNavigationButtonRender.Font = value;

            }

        }

        /// <summary>
        /// Gets or sets the tab gradient high color.
        /// </summary>
        public Color TabGradientHighColor
        {
            get
            {
                return this._defaultTabGradientHighColor;

            }

            set
            {
                if (value == this._defaultTabGradientHighColor)
                {
                    return;

                }

                this._defaultTabGradientHighColor = value;
                this._gradientNavigationButtonRender.GradientHighColor = value;

            }

        }

        /// <summary>
        /// Gets or sets the tab gradient low color.
        /// </summary>
        public Color TabGradientLowColor
        {
            get
            {
                return this._defaultTabGradientLowColor;

            }

            set
            {
                if (value == this._defaultTabGradientLowColor)
                {
                    return;

                }

                this._defaultTabGradientLowColor = value;
                this._gradientNavigationButtonRender.GradientLowColor = value;

            }

        }

        /// <summary>
        /// Gets or sets the tab height
        /// </summary>
        public int TabHeight
        {
            get
            {
                return this._tabHeight;

            }

            set
            {
                this._tabHeight = value;

            }

        }

        /// <summary>
        /// Gets or sets the gradient high (lighter) color for the tab when it is moused over.
        /// </summary>
        public Color TabHighlightGradientHighColor
        {
            get
            {
                return this._defaultTabHighlightGradientHighColor;

            }

            set
            {
                if (value == this._defaultTabHighlightGradientHighColor)
                {
                    return;

                }

                this._defaultTabHighlightGradientHighColor = value;
                this._gradientNavigationButtonRender.HighlightGradientHighColor = value;

            }

        }

        /// <summary>
        /// Gets or sets the gradient high (lighter) color for the tab when it is moused over.
        /// </summary>
        public Color TabHighlightGradientLowColor
        {
            get
            {
                return this._defaultTabHighlightGradientLowColor;

            }

            set
            {
                if (value == this._defaultTabHighlightGradientLowColor)
                {
                    return;

                }

                this._defaultTabHighlightGradientLowColor = value;
                this._gradientNavigationButtonRender.HighlightGradientLowColor = value;

            }

        }

        /// <summary>
        /// Gets or sets the default tab image alignment.
        /// </summary>
        public ContentAlignment TabImageAlign
        {
            get
            {
                return this._defaultTabImageAlign;

            }

            set
            {
                this._defaultTabImageAlign = value;
                this._gradientNavigationButtonRender.ImageAlign = value;

            }

        }

        /// <summary>
        /// Gets or sets the default tab text aligment.
        /// </summary>
        public ContentAlignment TabTextAlign
        {
            get
            {
                return this._defaultTabTextAlign;

            }

            set
            {
                this._defaultTabTextAlign = value;
                this._gradientNavigationButtonRender.TextAlign = value;

            }

        }

        /// <summary>
        /// Gets or sets the tab width
        /// </summary>
        public int TabWidth
        {
            get
            {
                return this._tabWidth;

            }

            set
            {
                this._tabWidth = value;

            }

        }

        /// <summary>
        /// Gets or sets number of tabs to display (render).
        /// </summary>
        public int DisplayTabCount
        {
            get
            {
                return this._displayButtonCount;

            }

            set
            {
                this._displayButtonCount = value;

            }

        }

        /// <summary>
        /// Gets or sets if the control should render text right to left.
        /// </summary>
        public bool RightToLeft
        {
            get 
            { 
                return this._rightToLeft;
            
            }

            set 
            {
                if (this._rightToLeft == value)
                {
                    return;

                }

                this._rightToLeft = value;

                this._gradientNavigationButtonRender.RightToLeft = value;
                
            }

        }

        /// <summary>
        /// Gets or sets the display order list.
        /// </summary>
        public ArrayList DisplayOrder
        {
            get
            {
                return this._displayOrder;

            }

        }

        /// <summary>
        /// Gets or sets a value that determines whether to use the compatible text rendering engine (GDI+) or not (GDI). 
        /// </summary>
        /// <value>
        /// true if the compatible text rendering engine (GDI+) is used; otherwise, false. 
        /// </value>
        public bool UseCompatibleTextRendering
        {
            get
            {
                return this._useCompatibleTextRendering;

            }

            set
            {
                this._useCompatibleTextRendering = value;

                this._gradientNavigationButtonRender.UseCompatibleTextRendering = value;

            }

        }

        #region IDisposable Members

        /// <summary>
        /// Releases all resources used.
        /// </summary>
        public void Dispose()
        {
            this.Dispose(true);

            GC.SuppressFinalize(this);

            return;

        }

        /// <summary>
        /// Releases all resources used.
        /// </summary>
        /// <param name="disposing">true or false</param>
        protected virtual void Dispose(bool disposing)
        {
            if (!this._disposed)
            {
                if (disposing)
                {
                    if (this._gradientNavigationButtonRender != null) this._gradientNavigationButtonRender.Dispose();

                }

            }

            this._disposed = true;

        }

        /// <summary>
        /// Creates the colors used to draw the control.
        /// </summary>
        /// <remarks>
        /// Takes the alpha and enabled into account.
        /// </remarks>
        protected void CreateColors()
        {
            if (this.Enabled)
            {
                if (this._borderColor.ShouldSerializeAll())
                {
                    this._adjustedBorderColorAll = this._borderColor.All;

                    this._adjustedBorderColorLeft = this._adjustedBorderColorAll;
                    this._adjustedBorderColorTop = this._adjustedBorderColorAll;
                    this._adjustedBorderColorRight = this._adjustedBorderColorAll;
                    this._adjustedBorderColorBottom = this._adjustedBorderColorAll;

                }
                else
                {
                    this._adjustedBorderColorLeft = this._borderColor.Left;
                    this._adjustedBorderColorTop = this._borderColor.Top;
                    this._adjustedBorderColorRight = this._borderColor.Right;
                    this._adjustedBorderColorBottom = this._borderColor.Bottom;

                }

            }
            else
            {
                if (this._borderColor.ShouldSerializeAll())
                {
                    ExtendedColor grayscaleBorderAll = new ExtendedColor(this._borderColor.All, 0.0d);
                    this._adjustedBorderColorAll = grayscaleBorderAll;

                }
                else
                {
                    ExtendedColor grayscaleBorderLeft = new ExtendedColor(this._borderColor.Left, 0.0d);
                    this._adjustedBorderColorLeft = grayscaleBorderLeft;

                    ExtendedColor grayscaleBorderTop = new ExtendedColor(this._borderColor.Top, 0.0d);
                    this._adjustedBorderColorTop = grayscaleBorderTop;

                    ExtendedColor grayscaleBorderRight = new ExtendedColor(this._borderColor.Right, 0.0d);
                    this._adjustedBorderColorRight = grayscaleBorderRight;

                    ExtendedColor grayscaleBorderBottom = new ExtendedColor(this._borderColor.Bottom, 0.0d);
                    this._adjustedBorderColorBottom = grayscaleBorderBottom;

                }

            }

        }

        /// <summary>
        /// Fires the event indicating that the control antialias has changed.  Inheriting controls should use this in favour of actually listening to the event, but should not forget to call base.OnAntiAliasChanged() to ensure that the event is still fired for external listeners.
        /// </summary>
        /// <param name="e">A System.EventArgs that contains the event data.</param>
        protected void OnAntiAliasChanged(EventArgs e)
        {
            this._gradientNavigationButtonRender.AntiAlias = this._antiAlias;

            if (this.AntiAliasChanged != null)
            {
                this.AntiAliasChanged(this, e);

            }

        }

        /// <summary>
        /// Fires the event indicating that the control Border has changed.  Inheriting controls should use this in favour of actually listening to the event, but should not forget to call base.OnBorderChanged() to ensure that the event is still fired for external listeners.
        /// </summary>
        /// <param name="e">A System.EventArgs that contains the event data.</param>
        protected void OnBorderChanged(EventArgs e)
        {
            if (this.BorderChanged != null)
            {
                this.BorderChanged(this, e);

            }

        }

        /// <summary>
        /// Fires the event indicating that the control BorderColor has changed.  Inheriting controls should use this in favour of actually listening to the event, but should not forget to call base.OnBorderColorChanged() to ensure that the event is still fired for external listeners.
        /// </summary>
        /// <param name="e">A System.EventArgs that contains the event data.</param>
        protected void OnBorderColorChanged(EventArgs e)
        {
            if (this.BorderColorChanged != null)
            {
                this.BorderColorChanged(this, e);

            }

        }

        /// <param name="e">An System.EventArgs that contains the event data.</param>
        protected virtual void OnEnabledChanged(System.EventArgs e)
        {
            this.CreateColors();

            if (this.EnabledChanged != null)
            {
                this.EnabledChanged(this, e);

            }

        }

        /// <summary>
        /// Renders the gradient background.
        /// </summary>
        /// <param name="e">Provides data for the Paint event.</param>
        public virtual void Render(PaintEventArgs e)
        {
            if (this.DisplayRectangle != null)
            {
                if (this.DisplayRectangle.Width > 0 && this.DisplayRectangle.Height > 0)
                {
                    int index = -1;

                    if (this._gradientTabSizeMode != GradientTabSizeMode.Fixed)
                    {
                        this._gradientNavigationButtonRender.Text = "Size";

                        Size size = this._gradientNavigationButtonRender.GetAutoSize();
                        if (this._tabHeight < (size.Height + 2))
                        {
                            this._tabHeight = (size.Height + 2);
                            this.Render(e);
                            return;

                        }

                    }

                    this.DetermineTabOverflowValues();

                    this.SetRenderingHints(e);
                    this.CreateColors();
                    this.DrawSquareBackgound(e);

                    this.SetTabLocationValues();

                    int currentTabLeft = 0;
                    int currentTabTop = this._tabTop;
                    int currentTabWidth = this._tabWidth;
                    int currentTabHeight = 0;
                    bool isFirstTab = true;

                    int displayedCount = this._parentGradientTab.GradientTabPages.DisplayCount;

                    Pen borderPen = new Pen(this._borderColor.Top);
                    try
                    {
                        int couldDrawCount = 1;

                        for (int i = 0; i < displayedCount; i++)
                        {
                            index = this._parentGradientTab.GradientTabPages.IndexOf(this._displayOrder[i].ToString());

                            if (index > -1)
                            {
                                if (this._parentGradientTab.GradientTabPages[index].Visible && this._parentGradientTab.GradientTabPages[index].TabVisible)
                                {
                                    if (couldDrawCount > this._startingTabIndexOffset)
                                    {
                                        if (i == this._activeIndex)
                                        {
                                            isFirstTab = false;

                                            this._gradientNavigationButtonRender.Active = true;
                                            currentTabHeight = this._tabHeight;
                                            currentTabTop = (this._tabTop + this._tabTopActiveOffset);
                                            this._gradientNavigationButtonRender.Border = new Border(1, 1, 1, 1);

                                            switch (this._alignment)
                                            {
                                                case GradientTabAlignment.Top:
                                                    this._gradientNavigationButtonRender.BorderColor = new BorderColor(this._adjustedBorderColorLeft, this._adjustedBorderColorLeft, this._adjustedBorderColorLeft, this._controlColor);
                                                    break;

                                                case GradientTabAlignment.Bottom:
                                                    this._gradientNavigationButtonRender.BorderColor = new BorderColor(this._adjustedBorderColorLeft, this._controlColor, this._adjustedBorderColorLeft, this._adjustedBorderColorBottom);
                                                    break;

                                                case GradientTabAlignment.Left:
                                                    this._gradientNavigationButtonRender.BorderColor = new BorderColor(this._adjustedBorderColorLeft, this._adjustedBorderColorLeft, this._controlColor, this._adjustedBorderColorBottom);
                                                    break;

                                                case GradientTabAlignment.Right:
                                                    this._gradientNavigationButtonRender.BorderColor = new BorderColor(this._controlColor, this._adjustedBorderColorLeft, this._adjustedBorderColorLeft, this._adjustedBorderColorBottom);
                                                    break;

                                            }

                                        }
                                        else
                                        {
                                            if (isFirstTab) currentTabLeft = 2;

                                            this._gradientNavigationButtonRender.Active = false;
                                            currentTabHeight = (this._tabHeight - 2);
                                            currentTabTop = (this._tabTop + this._tabTopOffset);

                                            this._gradientNavigationButtonRender.BorderColor = new BorderColor(this._adjustedBorderColorLeft);

                                            switch (this._alignment)
                                            {
                                                case GradientTabAlignment.Top:
                                                case GradientTabAlignment.Bottom:
                                                    if (i == (this._activeIndex + 1))
                                                    {
                                                        if (isFirstTab)
                                                        {
                                                            this._gradientNavigationButtonRender.Border = new Border(1, 1, 1, 1);

                                                        }
                                                        else
                                                        {
                                                            this._gradientNavigationButtonRender.Border = new Border(0, 1, 1, 1);

                                                        }

                                                    }
                                                    else
                                                    {
                                                        if (i == (this._activeIndex - 1))
                                                        {
                                                            this._gradientNavigationButtonRender.Border = new Border(1, 1, 0, 1);

                                                        }
                                                        else
                                                        {
                                                            this._gradientNavigationButtonRender.Border = new Border(1, 1, 1, 1);

                                                        }

                                                    }
                                                    break;

                                                case GradientTabAlignment.Left:
                                                case GradientTabAlignment.Right:
                                                    if (i == (this._activeIndex + 1))
                                                    {
                                                        this._gradientNavigationButtonRender.Border = new Border(1, 1, 1, 0);

                                                    }
                                                    else
                                                    {
                                                        if (i == (this._activeIndex - 1))
                                                        {
                                                            this._gradientNavigationButtonRender.Border = new Border(1, 0, 1, 1);

                                                        }
                                                        else
                                                        {
                                                            this._gradientNavigationButtonRender.Border = new Border(1, 1, 1, 1);

                                                        }

                                                    }
                                                    break;

                                            }

                                            isFirstTab = false;

                                        }

                                        this._gradientNavigationButtonRender.ImageAlign = this._parentGradientTab.GradientTabPages[index].ImageAlign;
                                        this._gradientNavigationButtonRender.TextAlign = this._parentGradientTab.GradientTabPages[index].TextAlign;
                                        this._gradientNavigationButtonRender.Text = this._parentGradientTab.GradientTabPages[index].Text;
                                        this._gradientNavigationButtonRender.Image = this._parentGradientTab.GradientTabPages[index].Image;
                                        this._gradientNavigationButtonRender.Font = this._parentGradientTab.GradientTabPages[index].TabFont;

                                        this._parentGradientTab.GradientTabPages[index].TabRectangle = new Rectangle(currentTabLeft, currentTabTop, this._parentGradientTab.GradientTabPages[index].TabRectangle.Width, currentTabHeight);
                                        this._gradientNavigationButtonRender.DisplayRectangle = this._parentGradientTab.GradientTabPages[index].TabRectangle;

                                        this._gradientNavigationButtonRender.ForeColor = this._parentGradientTab.GradientTabPages[index].TabForeColor;
                                        this._gradientNavigationButtonRender.GradientHighColor = this._parentGradientTab.GradientTabPages[index].GradientHighColor;
                                        this._gradientNavigationButtonRender.GradientLowColor = this._parentGradientTab.GradientTabPages[index].GradientLowColor;
                                        this._gradientNavigationButtonRender.ActiveGradientHighColor = this._parentGradientTab.GradientTabPages[index].ActiveGradientHighColor;
                                        this._gradientNavigationButtonRender.ActiveGradientLowColor = this._parentGradientTab.GradientTabPages[index].ActiveGradientLowColor;
                                        this._gradientNavigationButtonRender.HighlightGradientHighColor = this._parentGradientTab.GradientTabPages[index].HighlightGradientHighColor;
                                        this._gradientNavigationButtonRender.HighlightGradientLowColor = this._parentGradientTab.GradientTabPages[index].HighlightGradientLowColor;

                                        this._gradientNavigationButtonRender.Highlight = i == this._highlightIndex ? true : false;
                                        this._gradientNavigationButtonRender.Enabled = this._parentGradientTab.GradientTabPages[index].Enabled;

                                        this._gradientNavigationButtonRender.Render(e);

                                        currentTabLeft += this._gradientNavigationButtonRender.DisplayRectangle.Width;

                                    }
                                    else
                                    {
                                        this._parentGradientTab.GradientTabPages[index].TabRectangle = Rectangle.Empty;
                                    
                                    }

                                    couldDrawCount++;

                                }
                                else
                                {
                                    this._parentGradientTab.GradientTabPages[index].TabRectangle = Rectangle.Empty;
                                
                                }

                            }

                        }

                    }
                    catch
                    {
                        throw;

                    }
                    finally
                    {
                        borderPen.Dispose();

                    }

                    if (this._hasTabOverflow && (displayedCount > 1))
                    {
                        int height = (this._tabHeight - 6);

                        this._rightArrowButtonRectangle = new Rectangle((this.DisplayRectangle.Right - height), (this._tabTop + this._tabTopOffset + 2), height, height);

                        this._gradientNavigationButtonRenderArrow.RenderMode = this._renderMode;
                        this._gradientNavigationButtonRenderArrow.BorderColor = new BorderColor(this._adjustedBorderColorLeft);
                        this._gradientNavigationButtonRenderArrow.DisplayRectangle = this._rightArrowButtonRectangle;
                        this._gradientNavigationButtonRenderArrow.Image = TMF.AscendedThemeKit.Properties.Resources.RightArrow;
                        this._gradientNavigationButtonRenderArrow.Highlight = this._isRightArrowButtonHighlighted;
                        this._gradientNavigationButtonRenderArrow.Active = this._isRightArrowButtonActive;
                        this._gradientNavigationButtonRenderArrow.Enabled = this._isRightArrowButtonEnabled;

                        this._gradientNavigationButtonRenderArrow.Render(e);

                        this._leftArrowButtonRectangle = new Rectangle((this.DisplayRectangle.Right - (height * 2)), (this._tabTop + this._tabTopOffset + 2), height, height); ;

                        this._gradientNavigationButtonRenderArrow.DisplayRectangle = this._leftArrowButtonRectangle;
                        this._gradientNavigationButtonRenderArrow.Image = TMF.AscendedThemeKit.Properties.Resources.LeftArrow;
                        this._gradientNavigationButtonRenderArrow.Highlight = this._isLeftArrowButtonHighlighted;
                        this._gradientNavigationButtonRenderArrow.Active = this._isLeftArrowButtonActive;
                        this._gradientNavigationButtonRenderArrow.Enabled = this._isLeftArrowButtonEnabled;

                        this._gradientNavigationButtonRenderArrow.Render(e);

                    }

                }

            }

        }

        private void MoveActiveTabIntoView()
        {
            if (!this._multiline && this._hasTabOverflow)
            {
                int availableWidth = (this.DisplayRectangle.Width - (this._tabHeight * 2));
                int displayedCount = this._parentGradientTab.GradientTabPages.DisplayCount;
                int totalTabWidth = 0;
                int currentTabWidth = 0;
                int displayed = 0;

                for (int i = 0; i < displayedCount; i++)
                {
                    if (this._parentGradientTab.GradientTabPages[i].Visible && this._parentGradientTab.GradientTabPages[i].TabVisible)
                    {
                        if (i >= this._startingTabIndexOffset)
                        {
                            currentTabWidth = this._parentGradientTab.GradientTabPages[i].TabRectangle.Width;

                            if (i == this._activeIndex)
                            {
                                if (displayed > 0)
                                {
                                    if ((totalTabWidth + currentTabWidth) > availableWidth)
                                    {
                                        for (int x = displayed; x > 0; x--)
                                        {
                                            this.StartingTabIndexOffset++;

                                            int lastTabWidth = this._parentGradientTab.GradientTabPages[x].TabRectangle.Width;

                                            totalTabWidth -= lastTabWidth;

                                            if ((totalTabWidth + currentTabWidth) <= availableWidth)
                                            {
                                                break;

                                            }

                                        }

                                        break;

                                    }
                                    else
                                    {
                                        break;

                                    }

                                }
                                else
                                {
                                    break;

                                }

                            }
                            else
                            {
                                totalTabWidth += currentTabWidth;

                            }

                            displayed++;

                        }

                    }

                }

            }

        }

        private void DetermineTabOverflowValues()
        {
            if (!this._multiline)
            {
                int displayedCount = this._parentGradientTab.GradientTabPages.DisplayCount;
                int totalTabWidth = 0;
                int totalTabWidthBeforeActive = 0;
                bool hasActiveBeenFound = false;
                int currentTabWidth = 0;
                int availableWidth = (this.DisplayRectangle.Width - (this._tabHeight * 2));

                this._canShowTabIndex = 0;

                for (int i = 0; i < displayedCount; i++)
                {
                    if (this._parentGradientTab.GradientTabPages[i].Visible && this._parentGradientTab.GradientTabPages[i].TabVisible)
                    {                        
                        this._gradientNavigationButtonRender.Text = this._parentGradientTab.GradientTabPages[i].Text;
                        this._gradientNavigationButtonRender.Image = this._parentGradientTab.GradientTabPages[i].Image;
                        this._gradientNavigationButtonRender.Font = this._parentGradientTab.GradientTabPages[i].TabFont;
                        this._gradientNavigationButtonRender.ImageAlign = this._parentGradientTab.GradientTabPages[i].ImageAlign;
                        this._gradientNavigationButtonRender.TextAlign = this._parentGradientTab.GradientTabPages[i].TextAlign;

                        if (this._gradientTabSizeMode != GradientTabSizeMode.Fixed)
                        {
                            Size size = this._gradientNavigationButtonRender.GetAutoSize();
                            currentTabWidth = size.Width;

                        }
                        else
                        {
                            currentTabWidth = this._tabWidth;

                        }

                        if((totalTabWidth + currentTabWidth) < availableWidth)
                        {
                            this._canShowTabIndex++;

                        }

                        totalTabWidth += currentTabWidth;

                        Rectangle tabRectangle = new Rectangle(-1, -1, currentTabWidth, this._tabHeight);

                        this._parentGradientTab.GradientTabPages[i].TabRectangle = tabRectangle;

                        if (!hasActiveBeenFound)
                        {
                            if (!this._parentGradientTab.GradientTabPages[i].Active)
                            {
                                hasActiveBeenFound = true;

                            }
                            else
                            {
                                totalTabWidthBeforeActive += currentTabWidth;

                            }

                        }

                    }

                }

                if (totalTabWidth > this.DisplayRectangle.Width)
                {
                    this._hasTabOverflow = true;

                    if (this._startingTabIndexOffset > 0)
                    {

                    }

                }
                else
                {
                    this._hasTabOverflow = false;

                }

            }
            else
            {
                this._hasTabOverflow = false;

            }

        }

        /// <summary>
        /// Sets the rendering hints based on the AntiAlias property.
        /// </summary>
        /// <param name="e">A System.Windows.Forms.PaintEventArgs that contains the event data.</param>
        /// <remarks>
        /// This methid must be called before any drawing methods are called.
        /// </remarks>
        private void SetRenderingHints(System.Windows.Forms.PaintEventArgs e)
        {
            if (this._antiAlias)
            {
                e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
                e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;

            }
            else
            {
                e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SystemDefault;
                e.Graphics.SmoothingMode = SmoothingMode.Default;

            }

        }

        #endregion
        
        private void SetTabLocationValues()
        {
            switch (this._alignment)
            {
                case GradientTabAlignment.Top:
                    this._tabTop = 0;
                    this._tabTopActiveOffset = 1;
                    this._tabTopOffset = 3;
                    break;

                case GradientTabAlignment.Bottom:
                    this._tabTop = (this.DisplayRectangle.Bottom - this.TabHeight);
                    this._tabTopActiveOffset = 0;
                    this._tabTopOffset = 0;
                    break;
                    
            }

        }

        /// <summary>
        /// Fires the event indicating that the control backColor has changed.  Inheriting controls should use this in favour of actually listening to the event, but should not forget to call base.OnBackColorChanged() to ensure that the event is still fired for external listeners.
        /// </summary>
        /// <param name="e">A System.EventArgs that contains the event data.</param>
        public void OnBackColorChanged(EventArgs e)
        {
            if (this.BackColorChanged != null)
            {
                this.BackColorChanged(this, e);

            }

        }

        /// <summary>
        /// Draws a square background.
        /// </summary>
        /// <param name="e">Provides data for the Paint event.</param>
        private void DrawSquareBackgound(PaintEventArgs e)
        {
            SolidBrush backBrush = new SolidBrush(this.BackColor);
            try
            {
                e.Graphics.FillRectangle(backBrush, this.DisplayRectangle);

                SolidBrush panelBrush = new SolidBrush(this.ControlColor);
                try
                {
                    e.Graphics.FillRectangle(panelBrush, this.PanelRectangle);

                }
                catch
                {
                    throw;

                }
                finally
                {
                    panelBrush.Dispose();

                }

                Rectangle panelRectangle = this.PanelRectangle;

                if (this._border.Top > 0)
                {
                    Pen topBorderPen = new Pen(this._adjustedBorderColorTop, this._border.Top);
                    try
                    {
                        float offset = (float)(this._border.Top / 2.0);
                        e.Graphics.DrawLine(topBorderPen, new PointF(panelRectangle.Left, (panelRectangle.Top + offset)), new PointF(panelRectangle.Right, (panelRectangle.Top + offset)));

                    }
                    catch
                    {
                        throw;

                    }
                    finally
                    {
                        topBorderPen.Dispose();

                    }

                }

                if (this._border.Bottom > 0)
                {
                    Pen botttomBorderPen = new Pen(this._adjustedBorderColorBottom, this._border.Bottom);
                    try
                    {
                        float offset = (float)Math.Floor((this._border.Bottom / 2.0));
                        e.Graphics.DrawLine(botttomBorderPen, new PointF(panelRectangle.Left, (panelRectangle.Bottom - offset)), new PointF(panelRectangle.Right, (panelRectangle.Bottom - offset)));

                    }
                    catch
                    {
                        throw;

                    }
                    finally
                    {
                        botttomBorderPen.Dispose();

                    }

                }

                if (this._border.Right > 0)
                {
                    Pen rightBorderPen = new Pen(this._adjustedBorderColorRight, this._border.Right);
                    try
                    {
                        float offset = (float)Math.Floor((this._border.Right / 2.0));
                        e.Graphics.DrawLine(rightBorderPen, new PointF((panelRectangle.Right - offset), panelRectangle.Top), new PointF((panelRectangle.Right - offset), panelRectangle.Bottom));

                    }
                    catch
                    {
                        throw;

                    }
                    finally
                    {
                        rightBorderPen.Dispose();

                    }

                }

                if (this._border.Left > 0)
                {
                    Pen leftBorderPen = new Pen(this._adjustedBorderColorLeft, this._border.Left);
                    try
                    {
                        float offset = (float)(this._border.Left / 2.0);
                        e.Graphics.DrawLine(leftBorderPen, new PointF((panelRectangle.Left + offset), panelRectangle.Top), new PointF((panelRectangle.Left + offset), panelRectangle.Bottom));

                    }
                    catch
                    {
                        throw;

                    }
                    finally
                    {
                        leftBorderPen.Dispose();

                    }

                }

            }
            catch
            {
                throw;

            }
            finally
            {
                backBrush.Dispose();

            }

        }

        /// <summary>
        /// Resets the colors associated with the control.
        /// </summary>
        public virtual void ResetColors()
        {
            this.CreateColors();

            this._gradientNavigationButtonRender.ResetColors();

        }

        private void ResetRenderMode()
        {
            this._gradientNavigationButtonRender.RenderMode = this._renderMode;

        }

    }

}
